package com.osmino.contacts.dialer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import com.osmino.contacts.entity.Contact;
import com.osmino.contacts.entity.Phone;
import com.osmino.contacts.entity.Contact.PhotoState;
import com.osmino.contacts.history.CallLogCursorAdapter;
import com.osmino.contacts.provider.AsyncPhotoLoader;

public final class DialerAdapter extends BaseAdapter implements Filterable {

	protected final Context mContext;
	protected final CallLogCursorAdapter mCallLogAdapter;
	protected final CreateOrAddContactAdapter mCreateOrAddContactAdapter;
	protected List<Contact> mListOriginalContacts;
	protected final List<ContactPhonePositionHolder> mListContacts;
	protected Filter mFilter;
	protected CharSequence mConstraint;
	protected int mRegime;
	public static final int REGIME_CALLS = 0;
	public static final int REGIME_CONTACTS = 1;
	public static final int REGIME_OPTIONS = 2;

	public DialerAdapter(Context context, Cursor callLogCursor) {
		mContext = context;
		mCallLogAdapter = new CallLogCursorAdapter(mContext, callLogCursor);
		mCreateOrAddContactAdapter = new CreateOrAddContactAdapter(mContext);
		mListOriginalContacts = new ArrayList<Contact>();
		mListContacts = new ArrayList<ContactPhonePositionHolder>();
		mRegime = REGIME_CALLS;
	}

	@Override
	public int getViewTypeCount() {
		return 3;
	}

	@Override
	public int getItemViewType(int position) {
		return mRegime;
	}

	@Override
	public int getCount() {
		int size = 0;
		if (mRegime == REGIME_CALLS) {
			size = mCallLogAdapter.getCount();
		} else if (mRegime == REGIME_CONTACTS) {
			size = mListContacts.size();
		} else if (mRegime == REGIME_OPTIONS) {
			size = mCreateOrAddContactAdapter.getCount();
		}
		return size;
	}

	@Override
	public Object getItem(int position) {
		Object item = null;
		if (mRegime == REGIME_CALLS) {
			item = mCallLogAdapter.getItem(position);
		} else if (mRegime == REGIME_CONTACTS) {
			item = mListContacts.get(position).contact;
		} else if (mRegime == REGIME_OPTIONS) {
			item = mCreateOrAddContactAdapter.getItem(position);
		}
		return item;
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View item = null;
		if (mRegime == REGIME_CALLS) {
			item = mCallLogAdapter.getView(position, convertView, parent);
		} else if (mRegime == REGIME_OPTIONS) {
			item = mCreateOrAddContactAdapter.getView(position, convertView, parent);
		} else {
			if (convertView == null) {
				item = newContactView(position);
			} else {
				item = convertView;
			}
			bindContactView(position, item);
		}
		return item;
	}

	private View newContactView(int position) {
		View item = new ContactDialerItem(mContext);
		return item;
	}

	private void bindContactView(int position, View view) {
		ContactPhonePositionHolder holder = mListContacts.get(position);
		if (holder.contact.getPhotoState() == PhotoState.NOT_LOADED) {
			new AsyncPhotoLoader(mContext, this).execute(holder.contact);
		}
		ContactDialerItem dialerItem = (ContactDialerItem) view;
		dialerItem.setInfo(holder.contact, mConstraint.toString(), holder.phonePosition);
		dialerItem.setBackground(position % 2 != 0);
	}

	public void setListContacts(List<Contact> listContacts) {
		Collections.sort(listContacts, new Contact.ContactComparator());
		mListOriginalContacts = new ArrayList<Contact>(listContacts);
	}

	@Override
	public Filter getFilter() {
		if (mFilter == null) {
			mFilter = new PhoneNumberFilter();
		}
		return mFilter;
	}

	public int getRegime() {
		return mRegime;
	}

	private class PhoneNumberFilter extends Filter {

		public PhoneNumberFilter() {//
		}

		@Override
		protected FilterResults performFiltering(CharSequence constraint) {
			FilterResults results = new FilterResults();
			List<ContactPhonePositionHolder> resultList = new ArrayList<DialerAdapter.ContactPhonePositionHolder>();
			for (Contact contact : mListOriginalContacts) {
				int phoneSize = contact.getPhones().size();
				for (int i = 0; i < phoneSize; i++) {
					Phone phone = contact.getPhones().get(i);
					if (phone.number.replace("-", "").contains(constraint)) {
						ContactPhonePositionHolder item = new ContactPhonePositionHolder(contact, i);
						resultList.add(item);
						break;
					}
				}
			}
			results.values = resultList;
			results.count = resultList.size();
			return results;
		}

		@SuppressWarnings("unchecked")
		@Override
		protected void publishResults(CharSequence constraint, FilterResults results) {
			mConstraint = constraint;
			if (mConstraint == null || mConstraint.equals("")) {
				mRegime = REGIME_CALLS;
			} else {
				if (results.count > 0) {
					mRegime = REGIME_CONTACTS;
				} else {
					mRegime = REGIME_OPTIONS;
				}
			}
			mListContacts.clear();
			mListContacts.addAll((List<ContactPhonePositionHolder>) results.values);
			notifyDataSetInvalidated();
			notifyDataSetChanged();
		}
	}

	private static class ContactPhonePositionHolder {

		public final Contact contact;
		public final int phonePosition;

		public ContactPhonePositionHolder(Contact contact, int phonePosition) {
			this.contact = contact;
			this.phonePosition = phonePosition;
		}

	}
}
